package com.qubaopen.core.utils;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qubaopen.core.beans.DateJsonValueProcessor;


/**
 * 该类实现了JSON格式的数据输出功能
 * 
 * @author ZhangYongYi
 * 
 * @version 1.0
 */
public class JSONResponseUtil {
	private static Logger logger = LoggerFactory.getLogger("");

	/**
	 * 响应生成Grid格式的JSON数据集 <br>
	 * 'totalCount':Grid的JSONReader的totalProperty属性必须设置为"totalCount" <br>
	 * 'rows':Grid的JSONReader的root属性必须设置为"rows"
	 */
	public static void buildJSONDataResponse(HttpServletResponse response,
			String jsonString, Long total) {

		try {
			StringBuffer sb = new StringBuffer();
			sb.append("{\"totalCount\":" + total + ",\"rows\":");
			sb.append(jsonString);
			sb.append("}");

			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();

			out.write(sb.toString());
		} catch (IOException e) {
			logger.error("输出JSON数据流时发生异常:" + e.getMessage());
		}

	}

	/**
	 * 响应生成Grid格式的JSON数据集 <br>
	 * 'totalCount':Grid的JSONReader的totalProperty属性必须设置为"totalCount" <br>
	 * 'rows':Grid的JSONReader的root属性必须设置为"rows"
	 */
	public static void buildJSONDataResponse(HttpServletResponse response,
			List<? extends Object> data, Long total) {

		try {
			JSONArray jsonArray = JSONArray.fromObject(data);
			StringBuffer sb = new StringBuffer();
			sb.append("{\"totalCount\":" + total + ",\"rows\":");
			sb.append(jsonArray.toString());
			sb.append("}");

			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();

			out.write(sb.toString());
		} catch (IOException e) {
			logger.error("输出JSON数据流时发生异常:" + e.getMessage());
		}
	}

	/**
	 * 响应生成Grid格式的JSON数据集,数据集中包含Date类型的对象 <br>
	 * 'totalCount':Grid的JSONReader的totalProperty属性必须设置为"totalCount" <br>
	 * 'rows':Grid的JSONReader的root属性必须设置为"rows",
	 * 
	 * 日期格式可以为"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"等格式
	 */
	public static void buildDateJSONDataResponse(HttpServletResponse response,
			List<? extends Object> data, Long total, String dateFormat) {
		try {

			JSONArray jsonArray = JSONArray.fromObject(data,
					registerDateJsonConfig(dateFormat));
			StringBuffer sb = new StringBuffer();
			sb.append("{\"totalCount\":" + total + ",\"rows\":");
			sb.append(jsonArray.toString());
			sb.append("}");

			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();

			out.write(sb.toString());

		} catch (IOException e) {
			logger.error("输出含有Date类型数据的JSON数据流时发生异常:" + e.getMessage());
		}
	}

	/**
	 * 响应生成Grid格式的JSON数据集 <br>
	 * JSON对象的属性可以根据需要自定义设置，通过Map添加键值即可<br>
	 * 如: Map<String,Object> map = new HashMap<String,Object>();<br>
	 * map.put("totalCount",125);<br>
	 * map.put("success",true);<br>
	 * map.put("data",list);
	 */
	public static void buildCustomJSONDataResponse(
			HttpServletResponse response, Map<String, ? extends Object> data) {
		try {
			JSONObject jsonObject = JSONObject.fromObject(data);
			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.write(jsonObject.toString());
		} catch (IOException e) {
			logger.error("输出JSON数据流时发生异常:" + e.getMessage());
		}

	}

	/**
	 * 响应生成JSON格式的Map数据集 <br>
	 * JSON对象的属性可以根据需要自定义设置，通过Map添加键值即可<br>
	 * 如: Map<String,Object> map = new HashMap<String,Object>();<br>
	 * map.put("totalCount",125);<br>
	 * map.put("success",true);<br>
	 * map.put("data",list);
	 */
	public static void buildDateJSONDataResponse(HttpServletResponse response,
			Map<String, ? extends Object> data, String dateFormat)
			throws Exception {

		try {
			JSONObject jsonObject = JSONObject.fromObject(data,
					registerDateJsonConfig(dateFormat));
			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.write(jsonObject.toString());
		} catch (IOException e) {
			logger.error("输出含有Date类型数据的JSON数据流时发生异常:" + e.getMessage());
		}

	}

	/**
	 * 响应非Grid形式的JSON数据集的请求
	 */
	public static void buildJSONResponse(HttpServletResponse response,
			List<? extends Object> data) {
		try {
			JSONArray jsonArray = JSONArray.fromObject(data);
			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.write(jsonArray.toString());
		} catch (IOException e) {
			logger.error("输出JSON数据流时发生异常:" + e.getMessage());
		}

	}

	/**
	 * 响应含有Date类型数据的非Grid形式的JSON数据集的请求
	 */
	public static void buildDateJSONResponse(HttpServletResponse response,
			List<? extends Object> data, String dateFormat) {

		try {
			JSONArray jsonArray = JSONArray.fromObject(data,
					registerDateJsonConfig(dateFormat));
			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.write(jsonArray.toString());
		} catch (IOException e) {
			logger.error("输出含有Date类型数据的JSON数据流时发生异常:" + e.getMessage());
		}

	}

	/**
	 * 响应非Grid形式的JSON数据集的请求
	 */
	public static void buildJSONObjectResponse(HttpServletResponse response,
			JSONObject data) {
		try {
			response.setContentType("text/json; charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.write(data.toString());
		} catch (IOException e) {
			logger.error("输出JSON数据流时发生异常:" + e.getMessage());
		}

	}

	/**
	 * 为JSON对象注册Date数据的格式化方式
	 */
	private static JsonConfig registerDateJsonConfig(String dateFormat) {
		if (StringUtils.isEmpty(dateFormat)) {
			dateFormat = "yyyy-MM-dd";
		}

		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.registerJsonValueProcessor(java.util.Date.class,
				new DateJsonValueProcessor(dateFormat));
		jsonConfig.registerJsonValueProcessor(java.sql.Date.class,
				new DateJsonValueProcessor(dateFormat));

		return jsonConfig;
	}
}
